/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/* 
 * Copyright (c) 2009 City University of Hong Kong
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License m_version 2 as
 * published by the Free Software Foundation;
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 * 
 * Author: Wilson Thong (wilsonwk@ee.cityu.edu.hk) 
 */
#ifndef UNICAST_SESSION_HELPER_H
#define UNICAST_SESSION_HELPER_H

#include "jitter-sim-include.h"
#include "unicast-session-monitor.h"
#include "ns3/packet-sink-helper.h"
#include "ns3/udp-echo-helper.h"
#include "ns3/udp-echo-client.h"

namespace ns3 {
namespace eecityu {

/**
 * \brief Create an unicast traffic session between two nodes
 *
 * UnicastSessionHelper install a traffic source and a traffic sink
 * on two nodes. The underlaying traffic application is the UdpEchoClient,
 * and thus the attribute set for the traffic session aligns with the attributes
 * of the UdpEchoClient class.
 */
class UnicastSessionHelper : public RefCountBase 
{
public:
  /**
   * \brief Initialize the helper objects for installing traffic source and traffic
   * sink on nodes.
   */
  UnicastSessionHelper(void);
  /**
   * \brief Get source data rate 
   * \param src The UdpEchoClient object from which its data rate is read
   * \return The data rate
   */
  static DataRate GetSourceDataRate (Ptr<Application> src);
  /**
   * \return The source application just allocated by the InstallSession () method
   */
  const Ptr<Application> GetLastAllocatedSourceApplication () const;
  /**
   * \return The sink application just allocated by the InstallSession () method
   */
  const Ptr<Application> GetLastAllocatedSinkApplication () const;
  /**
   * \brief Install a session between a source node and a destination node
   *
   * \param src The node sourcing traffic
   * \param dst The node consuming traffic
   * \return A container containing the source application at the first place,
   * and the sink application at the second place.
   *
   * \see HandlePacketSentEvent (), HandlePacketReceivedEvent ()
   */
  ApplicationContainer InstallSession (Ptr<Node> src, Ptr<Node> dst);
  /**
   * \brief Create a monitor to trace the unicast session 
   * installed onto the source and destination nodes. 
   *
   * \param src The source node application of the unicast traffic session
   * \param dst The destination (or sink) node application of the unicast traffic session
   * \return UnicastSessionMonitor object to keep trace the performance
   * information regarding the unicast traffic between the two nodes
   */
  Ptr<UnicastSessionMonitor> CreateMonitor (Ptr<Application> src, Ptr<Application> dst);
  /**
   * \brief Configure the traffic source application - UdpEchoApplication
   *
   * \param name the name of the attribute to set
   * \param value the value of the attribute to set
   */
  void SetSourceAttribute (std::string name, const AttributeValue &value);
  /**
   * \brief Configure the traffic sink application - PacketSinkHelper
   *
   * \param name the name of the attribute to set
   * \param value the value of the attribute to set
   */
  void SetDestinationAttribute (std::string name, const AttributeValue &value);

private:
  ///**
  // * \brief Install traffic source and sink onto nodes without connecting trace sources
  // *
  // * This is the same as the InstallSession (), except that the two trace sources
  // * are not connected.
  // *
  // * \param src The node sourcing traffic
  // * \param dst The node consuming traffic
  // * \return A container containing the source application at the first place,
  // * and the sink application at the second place.
  // *
  // * \see InstallSession ()
  // */
  //ApplicationContainer InstallSessionWithTraceSource (Ptr<Node> src, Ptr<Node> dst);

  /// Helper class to create a traffic source
  UdpEchoClientHelper m_sourceHelper;
  /// Helper class to create a traffic sink
  PacketSinkHelper m_destinationHelper;
  /// Store the last source application just allocated to a source node
  Ptr<Application> m_lastAllocatedSourceApplication;
  /// Store the last sink application just allocated to a destination node
  Ptr<Application> m_lastAllocatedSinkApplication;
  /// A udp port to use for both the traffic source and traffic sink
  static const uint16_t BASE_UDP_PORT = 1024;
  // A factory to create UnicastSessionMonitor objects
  ObjectFactory m_monitorFactory;
};

} // namespace eecityu
} // namespace ns3

#endif // #define UNICAST_SESSION_HELPER_H
